// Copyright (c) 2008 Matthew Johnson
// Licensed under the MIT License (see license.txt)
package actionml.interaction {
	import actionml.Global;
	import actionml.ActionMLDocument;
	import actionml.core.LoadingUtils;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.utils.setTimeout;

	public class MediaInteractions {
		public static function initialize() {
			Global.initializeExtension(MediaInteractions, DisplayObject);
		}
		public static var instanceMethods:Object = {
			setBackgroundImage: function(b:Bitmap) {
				if (this.backgroundImage && this.parent.hasChild(this.backgroundImage)) {
					this.parent.removeChild(this.backgroundImage);
				}
				var image:Bitmap = new Bitmap(b.bitmapData, "auto", true);
				var aspectRatio:Number = image.getAspectRatio();
				//var r:Rectangle = this.getRect(this.parent);				var r:Rectangle = this.getBounds(this.parent);
				if (aspectRatio > this.getAspectRatio() && (!("bgScaleMode" in this) || this.bgScaleMode == "letterbox") || aspectRatio < this.getAspectRatio() && "bgScaleMode" in this && this.bgScaleMode == "crop") {
					image.width = r.width;
					image.height = Math.round(r.width / aspectRatio);					image.y = r.y + (r.height - image.height) / 3;
					image.x = r.x
				} else {
					image.height = r.height;
					image.width = Math.round(r.height * aspectRatio);					image.x = r.x + (r.width - image.width) / 2;
					image.y = r.y
				}
				this.parent.addChildAt(image, this.parent.getChildIndex(this));
				var s:Shape = new Shape();
				s.graphics.beginFill(0x000000);
				s.graphics.drawRect(this.x, this.y, r.width, r.height);
				this.parent.addChild(s);
				image.mask = s;
				this.backgroundImage = image; 
			},
			makeFilmstrip: function(options:Object = null) {
				options ||= {};
				var o:DisplayObject = this;
				var items:Array = [];
				this.addEventListener("init", function(e:Event) {
					o.removeEventListener("init", arguments.callee);
					for (var i:int = 0; i < o.numChildren; i++) {
						var child:DisplayObject = o.getChildAt(i);
						if (child is MovieClip) {
							items.push(child);
						}
					}
					var padding:Number = options["padding"] || 10;
					var itemWidth:Number = (o.width - ((items.length + 1) * padding)) / items.length;
					var itemHeight:Number = o.height - padding * 2;
					var nextX:Number = padding + (o.width - o.getRect(o.parent).width);
					var itemY:Number = padding + (o.height - o.getRect(o.parent).height);
					for each (var item:MovieClip in items) {
						item.y = itemY;
						item.x = nextX;
						item.width = itemWidth;
						item.height = itemHeight;
						nextX += itemWidth + padding;
					}
				});
			},
			loadBackgroundImage: function(options:Object = null) {
				if (this.isAlready("BackgroundImage")) return;
				options ||= {};
				var loadingIndicator:Object = this.getValueForKeypath(options["loadingIndicator"] || "loadingIndicator");
				if (loadingIndicator) {
					loadingIndicator.visible = true;
					loadingIndicator.play()
				}
				var o:DisplayObject = this;
				var initComplete:Boolean = false;
				var loadComplete:Boolean = false;
				o.bgScaleMode = options["bgScaleMode"] || "letterbox";
				function addBackgroundImage() {
					o.setBackgroundImage(o.backgroundImage);
					if (loadingIndicator) {
						loadingIndicator.playTween({alpha: 0});
					}
				}
				this.addEventListener("init", function(e:Event) {
					o.removeEventListener("init", arguments.callee);
					if (loadComplete) {
						addBackgroundImage();
					}
					initComplete = true;
				});
				LoadingUtils.loadSwfOrImage(options["bgImage"], {
					completeHandler: function(bitmap:Bitmap) {
						o.backgroundImage = bitmap;
						if (initComplete) {
							addBackgroundImage();							
						}
						loadComplete = true;
					}, 
					errorHandler: function(e:Object) {
						// TODO: trace error message
						trace("background image load error")
						trace(e)	
					}
				});
			},
			makeDynamicMedia: function(options:Object = null) {
				if (this.isAlready("DynamicMedia")) return;
				var source:String;
				var media:DisplayObject;
				var isActionMLDocument:Boolean = false;
				var interactions:String = options["interactions"];
				var content:String = options["content"];
				var o:DisplayObject = this;
				this.getInteractions = function() {
					if (interactions && isActionMLDocument) {
						return interactions;
					} else if (media && isActionMLDocument && media.interactions) {
						return media.interactions.toXMLString() || "";
					} else {
						return "";
					}
				};
				this.setInteractions = function(s:String) {
					interactions = s;
				};
				this.getContent = function() {
					if (content) {
						return content;
					} else if (media && isActionMLDocument && media.content) {
						return media.content.toXMLString() || "";
					} else {
						return "";
					}
				};
				this.setContent = function(s:String) {
					content = s;
				};
				this.getSource = function() {
					return source;
				};
				this.setSource = function(s:String) {
					if (!s) {
						// TODO trace error message
						return;
					}
					source = s;
					this.reload();
				};
				this.reload = function() {
					if (media) {
						try {
							media.loaderInfo.loader.unload();
						} catch (e:ArgumentError) {
							if (e.errorID == 2025) { // swallow unload error
								
							} else {
								throw e;
							}
						}
						this.removeChild(media);
						media = null;
					}
					LoadingUtils.loadSwfOrImage(source, {
						completeHandler: this.loadComplete, 
						errorHandler: this.loadError
					});
				};
				this.loadComplete = function(loaded:Object) {
					var timeoutComplete:Boolean = false;
					var loadingComplete:Boolean = false;
					setTimeout(function() {
						timeoutComplete = true;
						if (loadingComplete) {
							doLoadingComplete();
						}
					}, 500);
					o.addChild(loaded);
					if (loaded.width < o.width) {
						loaded.x = (o.width - loaded.width) / 2;
					} 
					if (loaded.height < o.height) {
						loaded.y = (o.height - loaded.height) / 3;
					}
					media = loaded;
					isActionMLDocument = false;
					for each (var c:Class in loaded["constructor"]["getClassHierarchy"]()) {
						if (c.toString() == "actionml::ActionMLDocument") {
							isActionMLDocument = true;
						}
					}
					if (isActionMLDocument) {
						if (interactions) {
							loaded.interactions = XML(interactions);
							if (content) {
								loaded.content = XML(content);
							}
						}
						loaded.addEventListener("loadingComplete", function() {
							loadingComplete = true;
							if (timeoutComplete) {
								doLoadingComplete();
							}
							loaded.removeEventListener("loadingComplete", arguments.callee);
						});
						loaded.load();
					} else {
						o.doEvent("loadingComplete");
					}					
					function doLoadingComplete() {
						if (interactions) {
							media.initialize();
							media.start();
						}
						o.doEvent("loadingComplete");
					}
				};
				this.loadError = function(e:Object) {
					// TODO: trace error message
					trace("load error")
					trace(e)	
				};
				if (options["source"].startsWith("(")) {
					options["source"] = o.evaluateExpression(options["source"].replace(/\(|\)/g, ""));
				}
				o.setSource(options["source"])
			}
		};
	}
}